
#
# A Production Rule System implemented in Python.
#
# (C) Copyright 2006-2008, Johan Lindberg
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA
#

import copy
import compiler
import logging

class ExecutionEnvironment(object):
    def __init__(self, rule_engine):
        self.logger = logging.getLogger('PyRete')
        
        self.rule_engine = rule_engine
        self.global_environment = self.rule_engine.env
        
        
    def execute_activation(self, activation):
        """
        Execute an activation (Rule + token) in the execution environment.
        """
        
        # Instead of keeping a list of activations that have been fired
        # we'll tag activations in the production nodes to make sure that
        # we don't fire the same activation twice (refraction)
        self.rule_engine._rete.remove_activation(activation)
        
        rule, salience, token, rhs, locals = activation
        rhs.filename = '<PyRete.%s>' % (rule)
        code = compiler.pycodegen.ExpressionCodeGenerator(rhs).getCode()
        
        env = self.global_environment
        env['assert_fact'] = self.rule_engine.assert_fact
        env['retract_fact'] = self.rule_engine.retract_fact
        env['modify_fact'] = self.rule_engine.modify_fact
        #env['modify_fact_attr'] = self.rule_engine.modify_fact_attr
        
        # Create local bindings by evaluating variables
        _locals = copy.copy(token)
        for var in locals:
            _locals[var] = eval(locals[var], token)
            
        # Execute the RHS
        exec(code, env, _locals)
        
if __name__ == '__main__':
    import doctest
    doctest.testmod()
    